package com.wuze.TCC.proxy;

import com.wuze.TCC.annotation.TCC;
import com.wuze.TCC.service.TCCManager;
import com.wuze.TCC.service.factory.TccManagerFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.UUID;


/**
 * 代理被TCC注解的类
 * @author wuze
 */
@Slf4j
public class CglibProxy implements MethodInterceptor {

    public Object target;

    public CglibProxy(Object target){
        this.target = target;
    }

    /**
     * @param obj: 代理对象
     * @param method: 被代理方法
     * @param args: 方法入参
     * @param methodProxy: CGLIB方法
     **/
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {


        TCC annotation = method.getAnnotation(TCC.class);
        //判断是否有TCC注解
        if (annotation != null) {
            log.info("开启TCC分布式事务");
            String transId = "";
            if (annotation.isInitiator()) {
                transId = UUID.randomUUID().toString();
            }else{
                transId = RpcContext.getContext().getAttachment("TransId");
            }

            TCCManager tccManager = TccManagerFactory.getTccManager();
            tccManager.doTry(transId,annotation, target, method , args);
            Object result = null;
            try {
                result = methodProxy.invoke(target, args);
                tccManager.doComfirm(transId,annotation, target, method , args);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
                tccManager.doCancel(transId,annotation, target, method , args);
            }


        }else {
            return methodProxy.invoke(target, args);
        }

        return null;
    }


}

